///PHILOTES Source Code.  (C)2012 PhiloLabs

#include "stdneb.h"
#include "log.h"
#include "logManager.h"
#include <iomanip>
#include <time.h>

namespace Core
{
	using namespace Util;
    //-----------------------------------------------------------------------
	Log::Log( const Util::String& name, bool debuggerOuput, bool suppressFile ) : 
        mLogLevel(LL_NORMAL), mDebugOut(debuggerOuput),
        mSuppressFile(suppressFile), mTimeStamp(true), mLogName(name)
    {
		if (!mSuppressFile)
		{
			mfpLog.open(name.AsCharPtr());
		}
    }
    //-----------------------------------------------------------------------
    Log::~Log()
    {
		//OGRE_LOCK_AUTO_MUTEX
		if (!mSuppressFile)
		{
	        mfpLog.close();
		}
    }
    //-----------------------------------------------------------------------
    void Log::logMessage( const String& message, LogMessageLevel lml, bool maskDebug )
    {
		//OGRE_LOCK_AUTO_MUTEX
        if ((mLogLevel + lml) >= PHILO_LOG_THRESHOLD)
        {
			SizeT size_ls = mListeners.Size();
			for (SizeT i = 0; i < size_ls; ++i)
				mListeners[i]->messageLogged( message, lml, maskDebug, mLogName );

			if (mDebugOut && !maskDebug)
                std::cerr << message.AsCharPtr() << std::endl;

            // Write time into log
			if (!mSuppressFile)
			{
				if (mTimeStamp)
			    {
                    struct tm *pTime;
                    time_t ctTime; time(&ctTime);
                    pTime = localtime( &ctTime );
                    mfpLog << std::setw(2) << std::setfill('0') << pTime->tm_hour
                        << ":" << std::setw(2) << std::setfill('0') << pTime->tm_min
                        << ":" << std::setw(2) << std::setfill('0') << pTime->tm_sec
                        << ": ";
                }
                mfpLog << message.AsCharPtr() << std::endl;

				// Flush stcmdream to ensure it is written (incase of a crash, we need log to be up to date)
				mfpLog.flush();
			}
        }
    }
    
    //-----------------------------------------------------------------------
    void Log::setTimeStampEnabled(bool timeStamp)
    {
		//OGRE_LOCK_AUTO_MUTEX
        mTimeStamp = timeStamp;
    }

    //-----------------------------------------------------------------------
    void Log::setDebugOutputEnabled(bool debugOutput)
    {
		//OGRE_LOCK_AUTO_MUTEX
        mDebugOut = debugOutput;
    }

	//-----------------------------------------------------------------------
    void Log::setLogDetail(LoggingLevel ll)
    {
		//OGRE_LOCK_AUTO_MUTEX
        mLogLevel = ll;
    }

    //-----------------------------------------------------------------------
    void Log::addListener(LogListener* listener)
    {
		//OGRE_LOCK_AUTO_MUTEX
        mListeners.Append(listener);
    }

    //-----------------------------------------------------------------------
    void Log::removeListener(LogListener* listener)
    {
		//OGRE_LOCK_AUTO_MUTEX
		IndexT i = mListeners.FindIndex(listener);
		if (i != InvalidIndex)
		{
			mListeners.EraseIndex(i);
		}
    }
	//---------------------------------------------------------------------
	Log::Stream Log::stream(LogMessageLevel lml, bool maskDebug) 
	{
		return Stream(this, lml, maskDebug);
	}
	//---------------------------------------------------------------------
	void __cdecl Log::Stream::write( const char* fmtString, ... )
	{
		va_list argList;
		va_start(argList, fmtString);
		Util::String str;
		str.FormatArgList(fmtString, argList);
		mTarget->logMessage(str, mLevel, mMaskDebug);
		va_end(argList);

	}

}//namespace Core
